<template>
  <div class="sample-tutorial">
    <div class="sample-container">
      <gc-spread-sheets class="sample-spreadsheets" @workbookInitialized="initSpread">
        <gc-worksheet>
        </gc-worksheet>
      </gc-spread-sheets>
      <div id="statusBar"></div>
    </div>
    <div class="options-container">
      <div class="option-row">
        <div class="inputContainer">
          <input id="selectedFile" type="file" accept=".sjs, .xlsx, .xlsm, .ssjson, .json, .csv"
                 v-on:change="selectedFileChange($event)"/>
          <button class="settingButton" id="open" v-on:click="open">打开文件</button>
          <div class="open-options">
            <div class="item" v-show="needShow('open', 'openMode')">
              <label for="open-openMode">OpenMode</label>
              <select id="open-openMode" v-model.number="openOptions.openMode">
                <option value="0">normal</option>
                <option value="1">lazy</option>
                <option value="2">incremental</option>
              </select>
            </div>
            <div class="item" v-show="needShow('open', 'includeStyles')">
              <input type="checkbox" id="open-includeStyles" v-model="openOptions.includeStyles"/>
              <label for="open-includeStyles">includeStyles</label>
            </div>
            <div class="item" v-show="needShow('open', 'includeFormulas')">
              <input type="checkbox" id="open-includeFormulas" v-model="openOptions.includeFormulas"/>
              <label for="open-includeFormulas">includeFormulas</label>
            </div>
            <div class="item" v-show="needShow('open', 'frozenColumnsAsRowHeaders')">
              <input type="checkbox" id="open-frozenColumnsAsRowHeaders"
                     v-model="openOptions.frozenColumnsAsRowHeaders"/>
              <label for="open-frozenColumnsAsRowHeaders">frozenColumnsAsRowHeaders</label>
            </div>
            <div class="item" v-show="needShow('open', 'frozenRowsAsColumnHeaders')">
              <input type="checkbox" id="open-frozenRowsAsColumnHeaders"
                     v-model="openOptions.frozenRowsAsColumnHeaders"/>
              <label for="open-frozenRowsAsColumnHeaders">frozenRowsAsColumnHeaders</label>
            </div>
            <div class="item" v-show="needShow('open', 'fullRecalc')">
              <input type="checkbox" id="open-fullRecalc" v-model="openOptions.fullRecalc"/>
              <label for="open-fullRecalc">fullRecalc</label>
            </div>
            <div class="item" v-show="needShow('open', 'dynamicReferences')">
              <input type="checkbox" id="open-dynamicReferences" v-model="openOptions.dynamicReferences"/>
              <label for="open-dynamicReferences">dynamicReferences</label>
            </div>
            <div class="item" v-show="needShow('open', 'calcOnDemand')">
              <input type="checkbox" id="open-calcOnDemand" v-model="openOptions.calcOnDemand"/>
              <label for="open-calcOnDemand">calcOnDemand</label>
            </div>
            <div class="item" v-show="needShow('open', 'includeUnusedStyles')">
              <input type="checkbox" id="open-includeUnusedStyles"
                     v-model="openOptions.includeUnusedStyles"/>
              <label for="open-includeUnusedStyles">includeUnusedStyles</label>
            </div>
            <div class="item" v-show="needShow('open', 'incrementalLoading')">
              <input type="checkbox" id="open-incrementalLoading" v-model="openOptions.incrementalLoading"/>
              <label for="open-incrementalLoading">incrementalLoading</label>
            </div>
            <div class="item" v-show="needShow('open', 'encoding')">
              <label for="open-encoding">encoding</label>
              <input type="text" id="open-encoding" v-model="openOptions.encoding"/>
            </div>
            <div class="item" v-show="needShow('open', 'rowDelimiter')">
              <label for="open-rowDelimiter">rowDelimiter</label>
              <input type="text" id="open-rowDelimiter" v-model="openOptions.rowDelimiter"/>
            </div>
            <div class="item" v-show="needShow('open', 'columnDelimiter')">
              <label for="open-columnDelimiter">columnDelimiter</label>
              <input type="text" id="open-columnDelimiter" v-model="openOptions.columnDelimiter"/>
            </div>
          </div>
        </div>
        <div class="inputContainer">
          <label for="saveFileType">FileType:</label>
          <select id="saveFileType" v-model="saveFileType">
            <option value="sjs">SJS</option>
            <option value="xlsx">Excel</option>
            <option value="ssjson">SSJson</option>
            <option value="csv">Csv</option>
          </select>
          <button class="settingButton" id="save" v-on:click="save">Save</button>
        </div>
        <button class="settingButton" id="save" v-on:click="toJSON">toJSON</button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import GC from "@grapecity-software/spread-sheets";
import {ref, toRaw} from "vue";
import '@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013lightGray.css'
import '@grapecity-software/spread-sheets-print';
import "@grapecity-software/spread-sheets-vue";
import "@grapecity-software/spread-sheets-io";
import '@grapecity-software/spread-sheets-shapes';
import '@grapecity-software/spread-sheets-charts';
import '@grapecity-software/spread-sheets-slicers';
import '@grapecity-software/spread-sheets-pivot-addon';
import '@grapecity-software/spread-sheets-reportsheet-addon';
import "@grapecity-software/spread-sheets-tablesheet";
import "@grapecity-software/spread-sheets-ganttsheet";
import '@grapecity-software/spread-sheets-resources-zh';

GC.Spread.Common.CultureManager.culture("zh-cn");
const openOptions = {
  openMode: 0,
  includeStyles: true,
  includeFormulas: true,
  frozenColumnsAsRowHeaders: false,
  frozenRowsAsColumnHeaders: false,
  fullRecalc: false,
  dynamicReferences: true,
  calcOnDemand: false,
  includeUnusedStyles: true,
  incrementalLoading: false,
  encoding: "UTF-8",
  rowDelimiter: "\r\n",
  columnDelimiter: ","
};
const saveOptions = {
  includeBindingSource: false,
  includeStyles: true,
  includeFormulas: true,
  saveAsView: false,
  rowHeadersAsFrozenColumns: false,
  columnHeadersAsFrozenRows: false,
  includeAutoMergedCells: false,
  includeCalcModelCache: false,
  saveR1C1Formula: false,
  includeUnusedNames: true,
  includeEmptyRegionCells: true,
  encoding: "UTF-8",
  rowDelimiter: "\r\n",
  columnDelimiter: ",",
  sheetIndex: 0,
  row: 0,
  column: 0,
  rowCount: 200,
  columnCount: 20,
};
const openOptionsConfig = {
  sjs: [
    {
      propName: "openMode",
      type: "select",
      displayText: "OpenMode",
      options: [{
        name: 'normal',
        value: 0
      }, {
        name: 'lazy',
        value: 1
      }, {
        name: 'incremental',
        value: 2
      }],
      default: 0
    },
    {
      propName: "includeStyles",
      type: "boolean",
      default: true
    },
    {
      propName: "includeFormulas",
      type: "boolean",
      default: true
    },
    {
      propName: "fullRecalc",
      type: "boolean",
      default: false
    },
    {
      propName: "dynamicReferences",
      type: "boolean",
      default: true
    },
    {
      propName: "calcOnDemand",
      type: "boolean",
      default: false
    },
    {
      propName: "includeUnusedStyles",
      type: "boolean",
      default: true
    }
  ],
  xlsx: [
    {
      propName: "openMode",
      type: "select",
      displayText: "OpenMode",
      options: [{
        name: 'normal',
        value: 0
      }, {
        name: 'lazy',
        value: 1
      }, {
        name: 'incremental',
        value: 2
      }],
      default: 0
    },
    {
      propName: "includeStyles",
      type: "boolean",
      default: true
    },
    {
      propName: "includeFormulas",
      type: "boolean",
      default: true
    },
    {
      propName: "frozenColumnsAsRowHeaders",
      type: "boolean",
      default: false
    },
    {
      propName: "frozenRowsAsColumnHeaders",
      type: "boolean",
      default: false
    },
    {
      propName: "fullRecalc",
      type: "boolean",
      default: false
    },
    {
      propName: "dynamicReferences",
      type: "boolean",
      default: true
    },
    {
      propName: "calcOnDemand",
      type: "boolean",
      default: false
    },
    {
      propName: "includeUnusedStyles",
      type: "boolean",
      default: true
    },
  ],
  ssjson: [
    {
      propName: "includeStyles",
      type: "boolean",
      default: true
    },
    {
      propName: "includeFormulas",
      type: "boolean",
      default: true
    },
    {
      propName: "frozenColumnsAsRowHeaders",
      type: "boolean",
      default: false
    },
    {
      propName: "frozenRowsAsColumnHeaders",
      type: "boolean",
      default: false
    },
    {
      propName: "fullRecalc",
      type: "boolean",
      default: false
    },
    {
      propName: "incrementalLoading",
      type: "boolean",
      default: false
    }
  ],
  csv: [
    {
      propName: "encoding",
      type: "string",
      default: "UTF-8"
    },
    {
      propName: "rowDelimiter",
      type: "string",
      default: "\r\n"
    },
    {
      propName: "columnDelimiter",
      type: "string",
      default: ","
    }
  ]
};
type FileType = 'sjs' | 'xlsx' | 'ssjson' | 'csv';
const saveOptionsConfig = {
  sjs: [{
    propName: "includeBindingSource",
    type: "boolean",
    default: false
  },
    {
      propName: "includeStyles",
      type: "boolean",
      default: true
    },
    {
      propName: "includeFormulas",
      type: "boolean",
      default: true
    },
    {
      propName: "saveAsView",
      type: "boolean",
      default: false
    },
    {
      propName: "includeAutoMergedCells",
      type: "boolean",
      default: false
    },
    {
      propName: "includeCalcModelCache",
      type: "boolean",
      default: false
    },
    {
      propName: "saveR1C1Formula",
      type: "boolean",
      default: false
    },
    {
      propName: "includeUnusedNames",
      type: "boolean",
      default: true
    },
    {
      propName: "includeEmptyRegionCells",
      type: "boolean",
      default: true
    },
  ],
  xlsx: [{
    propName: "includeBindingSource",
    type: "boolean",
    default: false
  },
    {
      propName: "includeStyles",
      type: "boolean",
      default: true
    },
    {
      propName: "includeFormulas",
      type: "boolean",
      default: true
    },
    {
      propName: "saveAsView",
      type: "boolean",
      default: false
    },
    {
      propName: "rowHeadersAsFrozenColumns",
      type: "boolean",
      default: false
    },
    {
      propName: "columnHeadersAsFrozenRows",
      type: "boolean",
      default: false
    },
    {
      propName: "includeAutoMergedCells",
      type: "boolean",
      default: false
    },
    {
      propName: "includeUnusedNames",
      type: "boolean",
      default: true
    },
    {
      propName: "includeEmptyRegionCells",
      type: "boolean",
      default: true
    },
  ],
  ssjson: [{
    propName: "includeBindingSource",
    type: "boolean",
    default: false
  },
    {
      propName: "includeStyles",
      type: "boolean",
      default: true
    },
    {
      propName: "includeFormulas",
      type: "boolean",
      default: true
    },
    {
      propName: "saveAsView",
      type: "boolean",
      default: false
    },
    {
      propName: "rowHeadersAsFrozenColumns",
      type: "boolean",
      default: false
    },
    {
      propName: "columnHeadersAsFrozenRows",
      type: "boolean",
      default: false
    },
    {
      propName: "includeAutoMergedCells",
      type: "boolean",
      default: false
    },
  ],
  csv: [{
    propName: "encoding",
    type: "string",
    default: "UTF-8"
  },
    {
      propName: "rowDelimiter",
      type: "string",
      default: "\r\n"
    },
    {
      propName: "columnDelimiter",
      type: "string",
      default: ","
    },
    {
      propName: "sheetIndex",
      type: "number",
      default: 0
    },
    {
      propName: "row",
      type: "number",
      default: 0
    },
    {
      propName: "column",
      type: "number",
      default: 0
    },
    {
      propName: "rowCount",
      type: "number",
      default: 200
    },
    {
      propName: "columnCount",
      type: "number",
      default: 20
    },
  ]
};
const spreadRef = ref<GC.Spread.Sheets.Workbook>();
const selectedFile = ref<any>(null);
const openFileType = ref<FileType>('xlsx');
const saveFileType = ref<FileType>('sjs');

const initSpread = function (spread: GC.Spread.Sheets.Workbook) {
  spreadRef.value = spread;
  // 底部状态栏：就绪、缩放，支持自定义
  const statusBarElement = document.getElementById('statusBar');
  if (statusBarElement) {
    let statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(statusBarElement);
    statusBar.bind(spread);
  }
}

const selectedFileChange = function (e: Event) {
  const target = e.target as HTMLInputElement;
  selectedFile.value = target.files?.[0];
  openFileType.value = getFileType(selectedFile.value) || 'xlsx';
}

const open = function () {
  let file = selectedFile.value;
  if (!file) {
    return;
  }

  let fileType = getFileType(file);
  let options = getOptions('open');
  let spread = toRaw(spreadRef.value)
  if (spread == undefined) return;
  if (fileType === 'sjs') {
    spread.open(file,
        function () {
        },
        function () {
        },
        options);
  } else {
    spread.import(file, function () {
      spread.removeSheet(0) // 删除默认的 授权说明sheet
      // spreadRef.value?.setActiveSheet('sheet1')
    }, function () {
    }, options);
  }
}

const save = function () {
  let fileType = saveFileType.value;
  let fileName = 'export.' + fileType;
  let options = getOptions('save');
  let spread = toRaw(spreadRef.value)
  if (spread == undefined) return;
  if (fileType === 'sjs') {
    spread.save(function (blob: Blob) {
      // 保存文件
      let a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = fileName;
      a.click();
      URL.revokeObjectURL(a.href);
    }, function () {
    }, options);
  } else {
    options.fileType = mapExportFileType(fileType);
    spread.export(function (blob: Blob) {
      let a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = fileName;
      a.click();
      URL.revokeObjectURL(a.href);
    }, function () {
    }, options);
  }
}

const getOptions = function (mode: string) {
  let optionsConfig, optionsValue;
  if (mode === 'open') {
    optionsConfig = openOptionsConfig[openFileType.value];
    optionsValue = openOptions;
  } else {
    optionsConfig = saveOptionsConfig[saveFileType.value];
    optionsValue = saveOptions;
  }

  let options: any = {};
  optionsConfig.forEach((prop: any) => {
    // @ts-ignore
    let v = optionsValue[prop.propName];
    if (prop.type === 'number') {
      v = +v;
    }
    options[prop.propName] = v;
  });

  return options;
}

const getFileType = function (file: File) {
  if (!file) {
    return '';
  }

  let fileName = file.name;
  let extensionName = fileName.substring(fileName.lastIndexOf(".") + 1);

  if (extensionName === 'sjs') {
    return 'sjs';
  } else if (extensionName === 'xlsx' || extensionName === 'xlsm') {
    return 'xlsx';
  } else if (extensionName === 'ssjson' || extensionName === 'json') {
    return 'ssjson';
  } else if (extensionName === 'csv') {
    return 'csv';
  }
}

const mapExportFileType = function (fileType: string) {
  if (fileType === 'ssjson') {
    return GC.Spread.Sheets.FileType.ssjson;
  } else if (fileType === 'csv') {
    return GC.Spread.Sheets.FileType.csv;
  }
  return GC.Spread.Sheets.FileType.excel;
}

const needShow = function (mode: string, propName: string) {
  let options = mode === 'open' ? openOptionsConfig[openFileType.value] : saveOptionsConfig[saveFileType.value];

  return options && options.find((p) => p.propName === propName);
}

const toJSON = () => {
  console.log('toJSON')
  const serializationOption = {
    includeBindingSource: true, // 将Spread实例序列化为JSON时，很容易包含它绑定到的实际数据源。如果您想在另一个Spread实例中加载那个JSON，您就不必担心再次将Spread绑定到数据源，因为它已经包含在其中了
    ignoreStyle: false, // 忽略样式可能会导致多次JSON转换的过程中,整体excel位移
    ignoreFormula: true, // ignore formulas when converting workbook to json, default value is false
    saveAsView: true, //include the format string formatting result when converting workbook to json, default value is false
    rowHeadersAsFrozenColumns: true, // treat row headers as frozen columns when converting workbook to json, default value is false
    columnHeadersAsFrozenRows: true, // treat column headers as frozen rows when converting workbook to json, default value is false
    includeAutoMergedCells: true // include the automatically merged cells to the real merged cells when converting the workbook to json.
  };
  const jsonOptions = {
    ignoreFormula: true, //
    ignoreStyle: false, // ignore styles when converting json to workbook, default value is false
    frozenColumnsAsRowHeaders: true, // treat the frozen columns as row headers when converting json to workbook, default value is false
    frozenRowsAsColumnHeaders: true, // treat the frozen rows as column headers when converting json to workbook, default value is false
    doNotRecalculateAfterLoad: true //  disable recalculation after loading the json, default value is false
  }
  let spread = toRaw(spreadRef.value)
  if (spread == undefined) return;
  const json = spread.toJSON(serializationOption);
  if (json) {
    // @ts-ignore
    json.name = Date.now()
  }
  // json太大时，需要构建json文件，把数据写进json文件用formdata传递给后端
  let file = new File([new Blob([JSON.stringify(json)], {type: 'application/json'})], Date.now() + '.json')
  let formData = new FormData();
  formData.append('file', file);
  console.log(file)
  // 把json往本地文件log.json里续写进去
  fetch('http://localhost:3000/log', {
    method: 'POST',
    body: formData
  }).then(res => {
    if (res.ok) {
      console.log('Log written successfully');
    } else {
      console.error('Failed to write log');
    }
  }).catch(err => {
    console.error('Error:', err);
  });

  if (json)
    spreadRef.value?.fromJSON(json, jsonOptions)
}
</script>

<style scoped>
.sample-tutorial {
  width: 1400px;
  height: 880px;
}

.sample-container {
  width: calc(100% - 280px);
  height: 100%;
  float: left;
}

.sample-spreadsheets {
  width: 100%;
  height: calc(100% - 25px);
  overflow: hidden;
}

#statusBar {
  bottom: 0;
  height: 25px;
  width: 100%;
  position: relative;
}

.options-container {
  float: right;
  width: 280px;
  height: 100%;
  box-sizing: border-box;
  background: #fbfbfb;
  overflow: auto;
}

.sample-options {
  z-index: 1000;
}

.inputContainer {
  width: 100%;
  height: auto;
  border: 1px solid #eee;
  padding: 6px 12px;
  margin-bottom: 10px;
  box-sizing: border-box;
}

.settingButton {
  color: #fff;
  background: #82bc00;
  outline: 0;
  line-height: 1.5715;
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  height: 32px;
  padding: 4px 15px;
  font-size: 14px;
  border-radius: 2px;
  user-select: none;
  cursor: pointer;
  border: 1px solid #82bc00;
  box-sizing: border-box;
  margin-bottom: 10px;
  margin-top: 10px;
}

.settingButton:hover {
  color: #fff;
  border-color: #88b031;
  background: #88b031;
}

.options-title {
  font-weight: bold;
  margin: 4px 2px;
}

#selectedFile {
  width: 180px;
}

#saveFileType {
  width: 120px;
  height: 31px;
}

.open-options .item {
  margin: 5px 0px;
  display: flex;
}

.save-options .item {
  margin: 5px 0px;
  display: flex;
}

label {
  margin-left: 3px;
}

select, input[type="text"], input[type="number"] {
  display: inline-block;
  margin-left: auto;
  width: 120px;
  font-weight: 400;
  outline: 0;
  line-height: 1.5715;
  border-radius: 2px;
  border: 1px solid #F4F8EB;
  box-sizing: border-box;
}
</style>
